Tracing hooks for VMX domains
authoradsharma@los-vmm.sc.intel.com <adsharma@los-vmm.sc.intel.com>
Thu, 25 Aug 2005 20:27:03 +0000 (13:27 -0700)
committeradsharma@los-vmm.sc.intel.com <adsharma@los-vmm.sc.intel.com>
Thu, 25 Aug 2005 20:27:03 +0000 (13:27 -0700)
The low level asm instrumentation is needed to get precise TSC counts.
trace=n should have precisely 0 overhead because of this patch.

Signed-off-by: Yunfeng Zhai <yunfeng.zhao@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
tools/xentrace/formats
xen/arch/x86/vmx.c
xen/arch/x86/x86_32/entry.S
xen/include/public/trace.h

index 8577590f2004097b83be18a8af78ee88e73b8b71..78954b9543c3b0873839dd275b80de33e54d692e 100644 (file)
@@ -15,3 +15,7 @@
 0x00080001     CPU%(cpu)d      %(tsc)d         VMX_VMEXIT              [ domid = 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
 0x00080002     CPU%(cpu)d      %(tsc)d         VMX_VECTOR              [ domid = 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
 0x00080003     CPU%(cpu)d      %(tsc)d         VMX_INT                 [ domid = 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
+
+0x00090001      CPU%(cpu)d      %(tsc)d         VMENTRY                 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+0x00090002      CPU%(cpu)d      %(tsc)d         VMEXIT                  0x%(1)08x 0x%(2)08x 0x%(3)08x 
+
index c19487d8d64369c99350305261a6e0ea06a5119e..56b5e4e04d3c121d2f81d6ec97d28ad7fb6e6c2a 100644 (file)
@@ -50,6 +50,13 @@ int vmcs_size;
 unsigned int opt_vmx_debug_level = 0;
 integer_param("vmx_debug", opt_vmx_debug_level);
 
+#ifdef TRACE_BUFFER
+static unsigned long trace_values[NR_CPUS][4];
+#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
+#else
+#define TRACE_VMEXIT(index,value) ((void)0)
+#endif
+
 #ifdef __x86_64__
 static struct msr_state percpu_msr[NR_CPUS];
 
@@ -381,6 +388,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
 
     if (!vmx_paging_enabled(current)){
         handle_mmio(va, va);
+        TRACE_VMEXIT (2,2);
         return 1;
     }
     gpa = gva_to_gpa(va);
@@ -393,12 +401,13 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
             __update_guest_eip(inst_len);
             return 1;
         }
+        TRACE_VMEXIT (2,2);
         handle_mmio(va, gpa);
         return 1;
     }
 
     result = shadow_fault(va, regs);
-
+    TRACE_VMEXIT (2,result);
 #if 0
     if ( !result )
     {
@@ -608,6 +617,7 @@ static void vmx_io_instruction(struct cpu_user_regs *regs,
         addr = (exit_qualification >> 16) & (0xffff);
     else
         addr = regs->edx & 0xffff;
+    TRACE_VMEXIT (2,addr);
 
     vio = get_vio(d->domain, d->vcpu_id);
     if (vio == 0) {
@@ -1282,13 +1292,20 @@ static int vmx_cr_access(unsigned long exit_qualification, struct cpu_user_regs
     case TYPE_MOV_TO_CR:
         gp = exit_qualification & CONTROL_REG_ACCESS_REG;
         cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+        TRACE_VMEXIT(1,TYPE_MOV_TO_CR);
+        TRACE_VMEXIT(2,cr);
+        TRACE_VMEXIT(3,gp);
         return mov_to_cr(gp, cr, regs);
     case TYPE_MOV_FROM_CR:
         gp = exit_qualification & CONTROL_REG_ACCESS_REG;
         cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+        TRACE_VMEXIT(1,TYPE_MOV_FROM_CR);
+        TRACE_VMEXIT(2,cr);
+        TRACE_VMEXIT(3,gp);
         mov_from_cr(cr, gp, regs);
         break;
     case TYPE_CLTS:
+        TRACE_VMEXIT(1,TYPE_CLTS);
         clts();
         setup_fpu(current);
 
@@ -1301,6 +1318,7 @@ static int vmx_cr_access(unsigned long exit_qualification, struct cpu_user_regs
         __vmwrite(CR0_READ_SHADOW, value);
         break;
     case TYPE_LMSW:
+        TRACE_VMEXIT(1,TYPE_LMSW);
         __vmread(CR0_READ_SHADOW, &value);
        value = (value & ~0xF) |
                (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
@@ -1544,6 +1562,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
 
     __vmread(GUEST_RIP, &eip);
     TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
+    TRACE_VMEXIT(0,exit_reason);
 
     switch (exit_reason) {
     case EXIT_REASON_EXCEPTION_NMI:
@@ -1562,6 +1581,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
             __vmx_bug(&regs);
         vector &= 0xff;
 
+        TRACE_VMEXIT(1,vector);
         perfc_incra(cause_vector, vector);
 
         TRACE_3D(TRC_VMX_VECTOR, v->domain->domain_id, eip, vector);
@@ -1606,6 +1626,10 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
         {
             __vmread(EXIT_QUALIFICATION, &va);
             __vmread(VM_EXIT_INTR_ERROR_CODE, &regs.error_code);
+            
+           TRACE_VMEXIT(3,regs.error_code);
+           TRACE_VMEXIT(4,va);
+
             VMX_DBG_LOG(DBG_LEVEL_VMMU, 
                         "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
                         (unsigned long)regs.eax, (unsigned long)regs.ebx,
@@ -1680,6 +1704,8 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
                 eip, inst_len, exit_qualification);
         if (vmx_cr_access(exit_qualification, &regs))
            __update_guest_eip(inst_len);
+        TRACE_VMEXIT(3,regs.error_code);
+        TRACE_VMEXIT(4,exit_qualification);
         break;
     }
     case EXIT_REASON_DR_ACCESS:
@@ -1692,6 +1718,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
         __get_instruction_length(inst_len);
         vmx_io_instruction(&regs, exit_qualification, inst_len);
+        TRACE_VMEXIT(4,exit_qualification);
         break;
     case EXIT_REASON_MSR_READ:
         __get_instruction_length(inst_len);
@@ -1726,6 +1753,25 @@ asmlinkage void load_cr2(void)
 #endif
 }
 
+#ifdef TRACE_BUFFER
+asmlinkage void trace_vmentry (void)
+{
+    TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0],
+          trace_values[current->processor][1],trace_values[current->processor][2],
+          trace_values[current->processor][3],trace_values[current->processor][4]);
+    TRACE_VMEXIT(0,9);
+    TRACE_VMEXIT(1,9);
+    TRACE_VMEXIT(2,9);
+    TRACE_VMEXIT(3,9);
+    TRACE_VMEXIT(4,9);
+    return;
+}
+asmlinkage void trace_vmexit (void)
+{
+    TRACE_3D(TRC_VMEXIT,0,0,0);
+    return;
+}
+#endif 
 #endif /* CONFIG_VMX */
 
 /*
index 911594b910c89d8d0da95bc8476fa25ee6e0497a..8e5442aa4b768772cff6973eb5b4e67f8f8a9a49 100644 (file)
 ENTRY(vmx_asm_vmexit_handler)
         /* selectors are restored/saved by VMX */
         VMX_SAVE_ALL_NOSEGREGS
+#ifdef TRACE_BUFFER
+        call trace_vmexit
+#endif
         call vmx_vmexit_handler
         jmp vmx_asm_do_resume
 
@@ -142,6 +145,9 @@ ENTRY(vmx_asm_vmexit_handler)
 /* vmx_restore_all_guest */
         call vmx_intr_assist
         call load_cr2
+#ifdef TRACE_BUFFER
+        call trace_vmentry
+#endif
         .endif
         VMX_RESTORE_ALL_NOSEGREGS
         /* 
index be412251041d874d14d97e3f03c4f4eadd706968..dfd55fdcf5183b1bc32a1b96ba1c8e4f5795eae8 100644 (file)
@@ -23,7 +23,7 @@
 #define TRC_VMXTIMER 0x00082000   /* VMX timer trace           */
 #define TRC_VMXINT   0x00084000   /* VMX interrupt trace       */
 #define TRC_VMXIO    0x00088000   /* VMX io emulation trace  */
-
+#define TRC_VMEXIT_HANDLER    0x00090000   /* VMX handler trace  */
 
 /* Trace events per class */
 
 
 #define TRC_VMX_INT             (TRC_VMXINT + 1)
 
+#define TRC_VMEXIT              (TRC_VMEXIT_HANDLER + 1)
+#define TRC_VMENTRY             (TRC_VMEXIT_HANDLER + 2)
+
+
 /* This structure represents a single trace buffer record. */
 struct t_rec {
     u64 cycles;               /* cycle counter timestamp */